package com.otherTest.java8.reduce;


import lombok.Data;
import org.junit.Test;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.Month;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Description: 测试lambda reduce功能
 * @author: conceit
 * @Date: 2018/7/20 0020
 * @see <a href="http://www.java2s.com/Tutorials/Java/Java_Stream/0230__Java_Stream_Reduce.htm"/>
 */
@SuppressWarnings("all")
public class TestReduce {


    /**
     * @Description: reduce 的第一个形参 identity the identity value for the accumulating function
     * 作为sum的起步数值
     * @author: conceit
     * @Date: 2018/7/20 0020
     */
    @Test
    public void diTestExampleOne() {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        int sun = numbers.stream().reduce(0, Integer::sum);
        System.out.println(sun);
    }


    /**
     * tomap 计算指定字段的总数
     *
     * @Description:
     * @author: conceit
     * @Date: 2018/7/20 0020
     */
    @Test
    public void doTestExampleTwo() {

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 8);
        Double incomeSum = TestReduce.persons().stream().map(Employee::getIncome).reduce(0.0D, Double::sum);
        System.out.println(incomeSum);

        //两种效果一样
        Double mapToDoubleIncomeSum = TestReduce.persons().stream().mapToDouble(Employee::getIncome).sum();
        System.out.println(mapToDoubleIncomeSum);


        //效果一样计算2至5位的所有工资总和
        AtomicLong forEachIncomeSum = new AtomicLong();
        TestReduce.persons().stream().limit(5).skip(2).forEach(n -> {
            forEachIncomeSum.addAndGet(new Double(n.getIncome()).longValue());
        });
        System.out.println(forEachIncomeSum);
    }

    @Test
    public void four() {
        //bigdecimalsum 求金额总和
        BigDecimal amount = TestReduce.persons().stream().map(Employee::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println(amount.toPlainString());
        //bigdecimalsum 求金额参与运算的个数
        Long count = TestReduce.persons().stream().map(Employee::getAmount).count();
        System.out.println(count);

        //bigdecimalsum 求金额最高的
        System.out.println(TestReduce.persons().stream().map(Employee::getAmount).max(BigDecimal::compareTo).get().toPlainString());
        //bigdecimalsum 求金额最低的
        System.out.println(TestReduce.persons().stream().map(Employee::getAmount).min(BigDecimal::compareTo).get().toPlainString());
        //取前两条最小的值
        System.out.println(TestReduce.persons().stream().map(Employee::getAmount).skip(0).limit(2).min(BigDecimal::compareTo).get().toPlainString());
    }

    public static List<Employee> persons() {
        Employee p1 = new Employee(1, "Jake", Employee.Gender.MALE, LocalDate.of(1971,
                Month.JANUARY, 1), 2343.0, new BigDecimal(10));
        Employee p2 = new Employee(2, "Jack", Employee.Gender.MALE, LocalDate.of(1972,
                Month.JULY, 21), 7100.0, new BigDecimal(9));
        Employee p3 = new Employee(3, "Jane", Employee.Gender.FEMALE, LocalDate.of(1973,
                Month.MAY, 29), 5455.0, new BigDecimal(99));
        Employee p4 = new Employee(4, "Jode", Employee.Gender.MALE, LocalDate.of(1974,
                Month.OCTOBER, 16), 1800.0, new BigDecimal(8.888));
        Employee p5 = new Employee(5, "Jeny", Employee.Gender.FEMALE, LocalDate.of(1975,
                Month.DECEMBER, 13), 1234.0, new BigDecimal(13.33));
        Employee p6 = new Employee(6, "Jason", Employee.Gender.MALE, LocalDate.of(1976,
                Month.JUNE, 9), 3211.0, new BigDecimal(11.11));

        List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6);

        return persons;
    }

    @Data
    static class Employee {

        public enum Gender {
            MALE, FEMALE
        }


        private long id;
        private String name;
        private Gender gender;
        private LocalDate dob;
        private double income;
        private BigDecimal amount;

        public Employee(long id, String name, Gender gender, LocalDate dob,
                        double income, BigDecimal amount) {
            this.id = id;
            this.name = name;
            this.gender = gender;
            this.dob = dob;
            this.income = income;
            this.amount = amount;
        }

        public long getId() {
            return id;
        }

        public String getName() {
            return name;
        }


    }
}
